package com.ruoyi.learn.java.design.pattern.creator;

import java.io.*;

/**
 * 演示各种单例模式的实现方式。
 * 包含：饿汉式、懒汉式（线程不安全/安全）、双重检查锁定、静态内部类、枚举。
 * 并演示了如何防止反射和序列化破坏单例。
 */
public class AllSingletons {

    //region 1. 饿汉式 (Eager Initialization)
    /**
     * 饿汉式单例。
     * 类加载时即创建实例，线程安全，但不支持懒加载。
     */
    public static class EagerSingleton {
        // 类加载时创建实例
        private static final EagerSingleton INSTANCE = new EagerSingleton();

        // 私有构造函数
        private EagerSingleton() {
            // 防止反射破坏（如果已存在实例则抛出异常）
            if (INSTANCE != null) {
                throw new RuntimeException("Use getInstance() to get the instance.");
            }
            System.out.println("EagerSingleton 构造函数被调用");
        }

        public static EagerSingleton getInstance() {
            return INSTANCE;
        }
    }
    //endregion

    //region 2. 懒汉式 (Lazy Initialization) - 线程不安全
    /**
     * 懒汉式单例（线程不安全）。
     * 第一次调用 getInstance() 时才创建实例，但多线程环境下可能创建多个实例。
     */
    public static class LazySingletonUnsafe {
        private static LazySingletonUnsafe instance;

        private LazySingletonUnsafe() {
            if (instance != null) {
                throw new RuntimeException("Use getInstance() to get the instance.");
            }
            System.out.println("LazySingletonUnsafe 构造函数被调用");
        }

        // 非线程安全
        public static LazySingletonUnsafe getInstance() {
            if (instance == null) {
                instance = new LazySingletonUnsafe();
            }
            return instance;
        }
    }
    //endregion

    //region 3. 懒汉式 (Lazy Initialization) - 线程安全 (同步方法)
    /**
     * 懒汉式单例（线程安全 - 同步方法）。
     * 使用 synchronized 保证线程安全，但性能较差（每次调用都同步）。
     */
    public static class LazySingletonSynchronized {
        private static LazySingletonSynchronized instance;

        private LazySingletonSynchronized() {
            if (instance != null) {
                throw new RuntimeException("Use getInstance() to get the instance.");
            }
            System.out.println("LazySingletonSynchronized 构造函数被调用");
        }

        // synchronized 保证线程安全，但性能差
        public static synchronized LazySingletonSynchronized getInstance() {
            if (instance == null) {
                instance = new LazySingletonSynchronized();
            }
            return instance;
        }
    }
    //endregion

    //region 4. 双重检查锁定 (Double-Checked Locking)
    /**
     * 双重检查锁定单例。
     * 线程安全，性能较好（只在初始化时同步），支持懒加载。
     * 必须使用 volatile 关键字防止指令重排序。
     */
    public static class DoubleCheckedLockingSingleton {
        // volatile 防止指令重排序
        private static volatile DoubleCheckedLockingSingleton instance;

        private DoubleCheckedLockingSingleton() {
            System.out.println("DoubleCheckedLockingSingleton 构造函数被调用1");

            // 防止反射破坏
            if (instance != null) {
                throw new RuntimeException("Use getInstance() to get the instance.");
            }
            System.out.println("DoubleCheckedLockingSingleton 构造函数被调用2");
        }

        public static DoubleCheckedLockingSingleton getInstance() {
            if (instance == null) { // 第一次检查
                synchronized (DoubleCheckedLockingSingleton.class) {
                    if (instance == null) { // 第二次检查
                        instance = new DoubleCheckedLockingSingleton();
                    }
                }
            }
            return instance;
        }

        // 防止序列化破坏
        private Object readResolve() {
            return instance;
        }
    }
    //endregion

    //region 5. 静态内部类 (Holder)
    /**
     * 静态内部类单例。
     * 利用类加载机制保证线程安全，支持懒加载，性能好。
     * 推荐实现方式之一。
     */
    public static class StaticInnerClassSingleton  implements java.io.Serializable {
        private static final long serialVersionUID = 1L; // 添加序列化版本ID

        private StaticInnerClassSingleton() {
            // 防止反射破坏
            if (SingletonHolder.INSTANCE != null) {
                throw new RuntimeException("Use getInstance() to get the instance.");
            }
            System.out.println("StaticInnerClassSingleton 构造函数被调用");
        }

        // 静态内部类
        private static class SingletonHolder {
            private static final StaticInnerClassSingleton INSTANCE = new StaticInnerClassSingleton();
        }

        public static StaticInnerClassSingleton getInstance() {
            return SingletonHolder.INSTANCE;
        }

        // 防止序列化破坏
        private Object readResolve() {
            return getInstance();
        }
    }
    //endregion

    //region 6. 枚举 (Enum) - 推荐最佳实践
    /**
     * 枚举单例。
     * Effective Java 推荐的最佳实践。
     * 天然线程安全，支持序列化/反序列化，防止反射攻击。
     * 代码最简洁。
     */
    public enum EnumSingleton {
        INSTANCE;

        // 可以添加方法
        public void doSomething() {
            System.out.println("EnumSingleton is doing something...");
        }
    }
    //endregion

    //region 7. 演示防止破坏单例的工具方法
    /**
     * 演示反射如何尝试破坏单例并如何防御。
     */
    public static void demonstrateReflectionAttack() {
        System.out.println("\n=== 演示反射攻击及防御 ===");
        try {
            // 尝试通过反射破坏 DoubleCheckedLockingSingleton
            java.lang.reflect.Constructor<DoubleCheckedLockingSingleton> constructor =
                    DoubleCheckedLockingSingleton.class.getDeclaredConstructor();
            constructor.setAccessible(true); // 暴力访问私有构造函数

            // 第一次创建 (应该成功)
            DoubleCheckedLockingSingleton instance1 = constructor.newInstance();
            System.out.println("第一次通过反射创建: " + instance1);

            // 第二次创建 (应该失败，因为构造函数中有检查)
            try {
                DoubleCheckedLockingSingleton instance2 = constructor.newInstance();
                System.out.println("第二次通过反射创建: " + instance2);
            } catch (Exception e) {
                System.out.println("反射攻击被阻止: " + e.getMessage());
            }

        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    /**
     * 演示序列化如何破坏单例并如何防御。
     */
    public static void demonstrateSerializationAttack() {
        System.out.println("\n=== 演示序列化攻击及防御 ===");
        try {
            // 创建原始实例
            StaticInnerClassSingleton original = StaticInnerClassSingleton.getInstance();
            System.out.println("原始实例: " + original);

            // 序列化到字节数组
            ByteArrayOutputStream bos = new ByteArrayOutputStream();
            ObjectOutputStream oos = new ObjectOutputStream(bos);
            oos.writeObject(original);
            oos.close();

            // 反序列化
            ByteArrayInputStream bis = new ByteArrayInputStream(bos.toByteArray());
            ObjectInputStream ois = new ObjectInputStream(bis);
            StaticInnerClassSingleton deserialized = (StaticInnerClassSingleton) ois.readObject();
            ois.close();

            System.out.println("反序列化后的实例: " + deserialized);
            System.out.println("两者是否为同一实例? " + (original == deserialized)); // 应该为 true

        } catch (Exception e) {
            e.printStackTrace();
        }
    }
    //endregion

    //region 8. 主函数 - 测试所有单例模式
    public static void main(String[] args) {
        System.out.println("=== 测试各种单例模式 ===\n");

        // 1. 测试饿汉式
        System.out.println("1. 饿汉式 (EagerSingleton):");
        EagerSingleton s1 = EagerSingleton.getInstance();
        EagerSingleton s2 = EagerSingleton.getInstance();
        System.out.println("s1 == s2 ? " + (s1 == s2));

        // 2. 测试懒汉式 (线程不安全 - 仅用于演示)
        System.out.println("\n2. 懒汉式 (线程不安全 - LazySingletonUnsafe):");
        LazySingletonUnsafe ls1 = LazySingletonUnsafe.getInstance();
        LazySingletonUnsafe ls2 = LazySingletonUnsafe.getInstance();
        System.out.println("ls1 == ls2 ? " + (ls1 == ls2));

        // 3. 测试懒汉式 (同步方法)
        System.out.println("\n3. 懒汉式 (同步方法 - LazySingletonSynchronized):");
        LazySingletonSynchronized lss1 = LazySingletonSynchronized.getInstance();
        LazySingletonSynchronized lss2 = LazySingletonSynchronized.getInstance();
        System.out.println("lss1 == lss2 ? " + (lss1 == lss2));

        // 4. 测试双重检查锁定
        System.out.println("\n4. 双重检查锁定 (DoubleCheckedLockingSingleton):");
        DoubleCheckedLockingSingleton dcl1 = DoubleCheckedLockingSingleton.getInstance();
        DoubleCheckedLockingSingleton dcl2 = DoubleCheckedLockingSingleton.getInstance();
        System.out.println("dcl1 == dcl2 ? " + (dcl1 == dcl2));

        // 5. 测试静态内部类
        System.out.println("\n5. 静态内部类 (StaticInnerClassSingleton):");
        StaticInnerClassSingleton sic1 = StaticInnerClassSingleton.getInstance();
        StaticInnerClassSingleton sic2 = StaticInnerClassSingleton.getInstance();
        System.out.println("sic1 == sic2 ? " + (sic1 == sic2));

        // 6. 测试枚举单例
        System.out.println("\n6. 枚举单例 (EnumSingleton):");
        EnumSingleton es1 = EnumSingleton.INSTANCE;
        EnumSingleton es2 = EnumSingleton.INSTANCE;
        System.out.println("es1 == es2 ? " + (es1 == es2));
        es1.doSomething();

        // 7. 演示防御机制
        demonstrateReflectionAttack();
        demonstrateSerializationAttack();

        System.out.println("\n=== 所有测试完成 ===");
    }
    //endregion
}
